package com.atguigu.tingshu.user.service.impl;

import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import com.atguigu.tingshu.album.AlbumFeignClient;
import com.atguigu.tingshu.common.constant.KafkaConstant;
import com.atguigu.tingshu.common.constant.RedisConstant;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.service.KafkaService;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.user.*;
import com.atguigu.tingshu.user.mapper.*;
import com.atguigu.tingshu.user.service.UserInfoService;
import com.atguigu.tingshu.vo.album.TrackListVo;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.atguigu.tingshu.vo.user.UserPaidRecordVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.service.WxService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private WxMaService wxMaService;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private KafkaService kafkaService;

    @Autowired
    private UserPaidAlbumMapper userPaidAlbumMapper;

    @Autowired
    private UserPaidTrackMapper userPaidTrackMapper;


    @Override
    @SneakyThrows
    public Map<String, String> wxLogin(String code) {
        //1.根据临时票据获取微信用户唯一标识openId
        WxMaJscode2SessionResult sessionInfo = wxMaService.getUserService().getSessionInfo(code);
        if (sessionInfo != null) {
            //2.根据openId查询数据库中用户账号
            String openid = sessionInfo.getOpenid();
            LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(UserInfo::getWxOpenId, openid);
            UserInfo userInfo = userInfoMapper.selectOne(queryWrapper);
            //2.1 如果账号不存在说明用户第一次进行微信登录
            if (userInfo == null) {
                //2.1.1 创建用户对象给用户基本信息赋值保存用户
                userInfo = new UserInfo();
                userInfo.setNickname("听友" + IdUtil.getSnowflakeNextIdStr());
                userInfo.setAvatarUrl("https://oss.aliyuncs.com/aliyun_id_photo_bucket/default_handsome.jpg");
                userInfo.setWxOpenId(openid);
                userInfoMapper.insert(userInfo);
                //2.1.2 发送Kafka消息通知账户系统初始化账号信息
                kafkaService.sendMessage(KafkaConstant.QUEUE_USER_REGISTER, userInfo.getId().toString());

            }
            //2.2 为当前登录账号生成Token令牌
            String token = IdUtil.simpleUUID();
            String loginKey = RedisConstant.USER_LOGIN_KEY_PREFIX + token;
            UserInfoVo userInfoVo = BeanUtil.copyProperties(userInfo, UserInfoVo.class);
            redisTemplate.opsForValue().set(loginKey, userInfoVo, RedisConstant.USER_LOGIN_KEY_TIMEOUT,
                    TimeUnit.MINUTES);

            Map<String, String> mapResult = new HashMap<>();
            mapResult.put("token", token);
            return mapResult;
        }
        return null;
    }

    @Override
    public UserInfoVo getUserInfoVoByUserId(Long userId) {
        //	获取到用户信息对象
        UserInfo userInfo = userInfoMapper.selectById(userId);
        if (userInfo != null) {
            //属性拷贝,创建UserInfoVo 对象
            UserInfoVo userInfoVo = BeanUtil.copyProperties(userInfo, UserInfoVo.class);
            return userInfoVo;
        }
        return null;
    }

    /**
     * 更新用户的信息
     *
     * @param userInfoVo
     * @param userId
     */

    @Override
    public void updateUser(UserInfoVo userInfoVo, Long userId) {
        UserInfo userInfo = new UserInfo();
        //只允许更新头像、昵称信息
        userInfo.setId(userId);
        userInfo.setNickname(userInfoVo.getNickname());
        userInfo.setAvatarUrl(userInfoVo.getAvatarUrl());

        //  执行更新方法
        userInfoMapper.updateById(userInfo);
    }

    /**
     * 获取用户声音列表付费情况
     *
     * @param userId
     * @param albumId
     * @param trackIdList
     * @return
     */
    @Override
    public Map<Long, Integer> userIsPaidTrackList(Long userId, Integer albumId, List<Long> trackIdList) {

        //1.根据用户id和专辑id查询专辑购买记录表user_paid_album  1
        // select *from  user_paid_album where user_id=? and album_id=?
        LambdaQueryWrapper<UserPaidAlbum> albumQueryWrapper = new LambdaQueryWrapper<>();
        //封装用户id
        albumQueryWrapper.eq(UserPaidAlbum::getUserId, userId);
        //封装专辑id
        albumQueryWrapper.eq(UserPaidAlbum::getAlbumId, albumId);
        //执行查询
        Long count = userPaidAlbumMapper.selectCount(albumQueryWrapper);
        //判断
        if (count > 0) {
            Map<Long, Integer> map = new HashMap<>();
            for (Long trackId : trackIdList) {
                map.put(trackId, 1);
            }
            return map;
        }

        //2.根据user_id album_id track_id 查询声音购买记录user_paid_track 如果为没有  0'
        //select*from user_paid_track where user_id =? and album_id=? and track_id in(trackIdList)
        LambdaQueryWrapper<UserPaidTrack> trackQueryWrapper = new LambdaQueryWrapper<>();
        trackQueryWrapper.eq(UserPaidTrack::getUserId, userId).eq(UserPaidTrack::getAlbumId, albumId);
        trackQueryWrapper.in(UserPaidTrack::getTrackId, trackIdList);

        //查询
        List<UserPaidTrack> userPaidTracks = userPaidTrackMapper.selectList(trackQueryWrapper);
        //判断
        if (CollectionUtil.isEmpty(userPaidTracks)) {

            Map<Long, Integer> map = new HashMap<>();
            for (Long trackId : trackIdList) {
                map.put(trackId, 0);
            }
            return map;
        }
        //3.获取购买的声音id，做判断
        List<Long> paidTackIdList =
                userPaidTracks.stream().map(userPaidTrack -> userPaidTrack.getTrackId()).collect(Collectors.toList());
        Map<Long, Integer> map = new HashMap<>();
        //处理
        for (Long trackId : trackIdList) {

            //判断
            if (paidTackIdList.contains(trackId)) {

                map.put(trackId, 1);
            } else {

                map.put(trackId, 0);
            }
        }
        return map;
    }

    /**
     * 判断用户是否购买过指定专辑
     *
     * @param userId
     * @param albumId
     * @return
     */
    @Override
    public Boolean isPaidAlbum(Long userId, Long albumId) {
        LambdaQueryWrapper<UserPaidAlbum> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserPaidAlbum::getUserId, userId);
        queryWrapper.eq(UserPaidAlbum::getAlbumId, albumId);
        Long count = userPaidAlbumMapper.selectCount(queryWrapper);
        return count > 0;
    }

    /**
     * 根据用户id和专辑id获取用户专辑声音的列表
     *
     * @param userId
     * @param albumId
     * @return
     */
    @Override
    public List<Long> findUserPaidTrackList(Long userId, Long albumId) {
        LambdaQueryWrapper<UserPaidTrack> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserPaidTrack::getUserId, userId);
        queryWrapper.eq(UserPaidTrack::getAlbumId, albumId);
        List<UserPaidTrack> userPaidTrackList = userPaidTrackMapper.selectList(queryWrapper);
        if (CollectionUtil.isNotEmpty(userPaidTrackList)) {
            //获取已经购买的声音列表
            List<Long> collect = userPaidTrackList.stream().map(UserPaidTrack::getTrackId).collect(Collectors.toList());
            return collect;
        }
        return null;
    }


    @Autowired
    private UserVipServiceMapper userVipServiceMapper;

    @Autowired
    private VipServiceConfigMapper vipServiceConfigMapper;

    @Autowired
    private AlbumFeignClient albumFeignClient;

    /**
     * 处理用户购买记录
     * 1.处理声音购买记录-根据订单编号避免重复增加购买记录
     * 2.处理专辑购买记录-根据订单编号避免重复增加购买记录
     * 3.处理会员购买记录
     * -根据订单编号避免重复增加购买记录
     * -修改用户表VIP状态及失效时间
     *
     * @param userPaidRecordVo
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveUserPayRecord(UserPaidRecordVo userPaidRecordVo) {
//1.处理声音购买记录
        if (SystemConstant.ORDER_ITEM_TYPE_TRACK.equals(userPaidRecordVo.getItemType())) {
            //1.1 根据订单编号避免重复增加购买记录
            LambdaQueryWrapper<UserPaidTrack> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(UserPaidTrack::getOrderNo, userPaidRecordVo.getOrderNo());
            Long count = userPaidTrackMapper.selectCount(queryWrapper);
            if (count > 0) {
                return;
            }
            //1.2 构建声音购买记录新增
            //1.3 远程调用专辑服务获取声音信息
            TrackInfo trackInfo = albumFeignClient.getTrackInfo(userPaidRecordVo.getItemIdList().get(0)).getData();

            userPaidRecordVo.getItemIdList().forEach(trackId -> {
                UserPaidTrack userPaidTrack = new UserPaidTrack();
                userPaidTrack.setOrderNo(userPaidRecordVo.getOrderNo());
                userPaidTrack.setUserId(userPaidRecordVo.getUserId());
                userPaidTrack.setAlbumId(trackInfo.getAlbumId());
                userPaidTrack.setTrackId(trackId);
                userPaidTrackMapper.insert(userPaidTrack);
            });
        } else if (SystemConstant.ORDER_ITEM_TYPE_ALBUM.equals(userPaidRecordVo.getItemType())) {
            //2.处理专辑购买记录
            //2.1 根据订单编号避免重复增加购买记录
            LambdaQueryWrapper<UserPaidAlbum> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(UserPaidAlbum::getOrderNo, userPaidRecordVo.getOrderNo());
            Long count = userPaidAlbumMapper.selectCount(queryWrapper);
            if (count > 0) {
                return;
            }
            //2.2 新增专辑购买记录
            userPaidRecordVo.getItemIdList().forEach(albumId -> {
                UserPaidAlbum userPaidAlbum = new UserPaidAlbum();
                userPaidAlbum.setOrderNo(userPaidRecordVo.getOrderNo());
                userPaidAlbum.setUserId(userPaidRecordVo.getUserId());
                userPaidAlbum.setAlbumId(albumId);
                userPaidAlbumMapper.insert(userPaidAlbum);
            });
        } else if (SystemConstant.ORDER_ITEM_TYPE_VIP.equals(userPaidRecordVo.getItemType())) {
            //3.处理会员购买记录
            //3.1-根据订单编号避免重复增加购买记录
            LambdaQueryWrapper<UserVipService> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(UserVipService::getOrderNo, userPaidRecordVo.getOrderNo());
            Long count = userVipServiceMapper.selectCount(queryWrapper);
            if (count > 0) {
                return;
            }
            //3.2-修改用户表VIP状态及失效时间
            Date startTime = new Date();
            //2.1.1 获取用户
            UserInfo userInfo = userInfoMapper.selectById(userPaidRecordVo.getUserId());
            //2.1.2 根据套餐ID查询VIP套餐信息
            VipServiceConfig vipServiceConfig = vipServiceConfigMapper.selectById(userPaidRecordVo.getItemIdList().get(0));
            Date expireTime = new Date();


            //刚购买VIP VIP开始时间-当前，过期时间：当前时间+购买月数
            //已是VIP且在有效期，过期时间：现有失效时间+购买月数
            if (userInfo.getIsVip() == 1 && userInfo.getVipExpireTime().after(new Date())) {
                expireTime = DateUtil.offsetMonth(userInfo.getVipExpireTime(), vipServiceConfig.getServiceMonth());
            } else {
                //首次购买会员-过期时间
                expireTime = DateUtil.offsetMonth(startTime, vipServiceConfig.getServiceMonth());
            }
            userInfo.setIsVip(1);
            userInfo.setVipExpireTime(expireTime);
            userInfoMapper.updateById(userInfo);

            //3.3-新增用户VIP购买记录
            for (Long vipConfigId : userPaidRecordVo.getItemIdList()) {
                UserVipService userVipService = new UserVipService();
                userVipService.setOrderNo(userPaidRecordVo.getOrderNo());
                userVipService.setUserId(userPaidRecordVo.getUserId());
                userVipService.setStartTime(startTime);
                userVipService.setExpireTime(expireTime);
                userVipService.setIsAutoRenew(0);
                userVipService.setNextRenewTime(null);
                userVipServiceMapper.insert(userVipService);
            }
        }
    }

    /**
     * 更新VIP的状态
     */
    @Override
    public void updateVipExpireStatus() {
        //1.已经过期的会员
        LambdaQueryWrapper<UserInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(UserInfo::getIsVip,1);
        queryWrapper.lt(UserInfo::getVipExpireTime,DateUtil.beginOfDay(new Date()));
        List<UserInfo> list = this.list(queryWrapper);
        //修改VIP的状态
        if (CollectionUtil.isNotEmpty(list)){
            List<UserInfo> collect = list.stream().map(userInfo -> {
                UserInfo userInfo1 = new UserInfo();
                userInfo1.setIsVip(0);
                userInfo1.setId(userInfo1.getId());
                return userInfo1;
            }).collect(Collectors.toList());
            this.updateBatchById(collect);
        }
    }
}
